#include <fcntl.h>
// #include <linux/ext4_fs.h>
#include <linux/fs.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

// 定义EXT4_N_BLOCKS
#define EXT4_N_BLOCKS 15

// 虚拟EXT4超级块结构
struct ext4_super_block {
    uint32_t s_inodes_count;          // Inode总数
    uint32_t s_blocks_count;          // 块总数
    uint32_t s_blocks_count_lo;       // 块总数的低位字
    uint32_t s_blocks_count_hi;       // 块总数的高位字
    uint32_t s_log_block_size;        // 块大小的对数
    uint32_t s_inode_size;            // Inode大小
    uint16_t s_reserved;              // 保留字段
    uint16_t s_free_blocks_count;     // 空闲块数
    uint16_t s_free_blocks_count_lo;  // 空闲块的低位字
    uint32_t s_free_blocks_count_hi;  // 空闲块的高位字
    uint16_t s_free_inodes_count;     // 空闲Inode数
    // 添加更多超级块字段...
};

// EXT4组描述符结构
struct ext4_group_desc {
    uint32_t bg_block_bitmap;       // 块位图的块号，指示数据块的分配情况
    uint32_t bg_inode_bitmap;       // Inode位图的块号，指示Inode的分配情况
    uint32_t bg_inode_table;        // Inode表的块号，包含文件和目录的Inode条目
    uint16_t bg_free_blocks_count;  // 组内未分配的空闲数据块数
    uint16_t bg_free_inodes_count;  // 组内未分配的空闲Inode数
    uint16_t bg_used_dirs_count;    // 组内使用的目录数
    // 添加更多组描述符字段...
};

// EXT4块位图结构
struct ext4_block_bitmap {
    // 块位图字段
    uint8_t* bitmap;  // 块位图数据
    // 添加更多块位图字段...
};

// EXT4 Inode位图结构
struct ext4_inode_bitmap {
    // Inode位图字段
    uint8_t* bitmap;  // Inode位图数据
    // 添加更多Inode位图字段...
};

// 虚拟EXT4 inode结构
struct ext4_inode {
    uint16_t i_mode;                  // Inode的文件类型和权限标志
    uint16_t i_uid;                   // 文件的所有者用户ID
    uint32_t i_size;                  // 文件的大小（字节数）
    uint64_t i_block[EXT4_N_BLOCKS];  // 数据块指针，用于指示文件数据块的位置

    // 添加更多inode字段...
};

// 打印ext4超级块信息
void print_superblock(struct ext4_super_block* sb) {
    printf("EXT4 Superblock Information:\n");
    printf("Inode count: %u\n", sb->s_inodes_count);
    printf("Block count: %llu\n", sb->s_blocks_count);
    printf("Inode size: %u bytes\n", sb->s_inode_size);
    printf("Block size: %u bytes\n", 1024 << sb->s_log_block_size);
    printf("Total inodes: %u\n", sb->s_inodes_count);
    printf("Total blocks: %llu\n", sb->s_blocks_count);
    printf("Blocks used: %llu\n", sb->s_blocks_count - sb->s_free_blocks_count);
    printf("Blocks free: %llu\n", sb->s_free_blocks_count);
    printf("Inodes used: %u\n", sb->s_inodes_count - sb->s_free_inodes_count);
    printf("Inodes free: %u\n", sb->s_free_inodes_count);
    // 添加更多超级块字段...
}

// 打印ext4组描述符信息
void print_group_descriptor(struct ext4_group_desc* gd) {
    printf("EXT4 Group Descriptor Information:\n");
    printf("Block bitmap: %u\n", gd->bg_block_bitmap);
    printf("Inode bitmap: %u\n", gd->bg_inode_bitmap);
    // 添加更多组描述符字段...
}

// 打印文件权限信息
void print_file_permissions(struct ext4_inode* inode) {
    // 获取文件类型和权限位
    uint16_t mode = inode->i_mode;

    // 文件类型和权限位的定义可以在 ext4 文档中找到
    // 例如，常见的文件类型包括：普通文件、目录、符号链接等
    // 权限位包括：读、写、执行权限
    printf("File Permissions:\n");
    printf("Is Directory: %s\n", (S_ISDIR(mode) ? "Yes" : "No"));
    printf("Owner Permissions: %c%c%c\n", (mode & S_IRUSR ? 'r' : '-'), (mode & S_IWUSR ? 'w' : '-'), (mode & S_IXUSR ? 'x' : '-'));
    printf("Group Permissions: %c%c%c\n", (mode & S_IRGRP ? 'r' : '-'), (mode & S_IWGRP ? 'w' : '-'), (mode & S_IXGRP ? 'x' : '-'));
    printf("Others Permissions: %c%c%c\n", (mode & S_IROTH ? 'r' : '-'), (mode & S_IWOTH ? 'w' : '-'), (mode & S_IXOTH ? 'x' : '-'));
}

// 读取并打印inode的数据块号码
void print_inode_data_blocks(int fd, struct ext4_inode* inode) {
    printf("Inode Data Blocks Information:\n");
    // 只考虑常规文件
    if (S_ISREG(inode->i_mode)) {
        for (int i = 0; i < EXT4_N_BLOCKS; i++) {
            printf("Block Pointer[%d]: %llu\n", i, inode->i_block[i]);
        }
    } else if (S_ISDIR(inode->i_mode)) {
        // 处理目录文件的数据块
        printf("这是目录文件\n");
    } else {
        // 处理其他文件类型的数据块
        printf("这是其它类型的数据块\n");
    }
    // 添加更多处理不同文件类型的数据块的逻辑...
}

// 打印块位图信息
void print_block_bitmap(int fd, struct ext4_group_desc* gd) {
    printf("EXT4 Block Bitmap Information:\n");
    struct stat file_stat;

    if (fstat(fd, &file_stat) == -1) {
        perror("fstat");
        return;
    }

    off_t block_size = file_stat.st_blksize;
    uint8_t bitmap_buffer[block_size];

    if (pread(fd, bitmap_buffer, block_size, gd->bg_block_bitmap * block_size) == -1) {
        perror("pread");
        return;
    }

    printf("Block Bitmap (first 8 bytes): ");
    for (int i = 0; i < 8; i++) {
        printf("%02X ", bitmap_buffer[i]);
    }
    printf("\n");

    // 解析和打印更多位图信息...
}

// 打印inode位图信息
void print_inode_bitmap(int fd, struct ext4_group_desc* gd) {
    printf("EXT4 Inode Bitmap Information:\n");
    struct stat file_stat;

    if (fstat(fd, &file_stat) == -1) {
        perror("fstat");
        return;
    }

    off_t block_size = file_stat.st_blksize;
    uint8_t bitmap_buffer[block_size];

    if (pread(fd, bitmap_buffer, block_size, gd->bg_inode_bitmap * block_size) == -1) {
        perror("pread");
        return;
    }

    printf("Inode Bitmap (first 8 bytes): ");
    for (int i = 0; i < 8; i++) {
        printf("%02X ", bitmap_buffer[i]);
    }
    printf("\n");

    // 解析和打印更多位图信息...
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <device_file>\n", argv[0]);
        return 1;
    }

    const char* device_file = argv[1];
    int fd = open(device_file, O_RDONLY);

    if (fd == -1) {
        perror("open");
        return 1;
    }

    // 读取ext4超级块
    struct ext4_super_block sb;
    if (pread(fd, &sb, sizeof(sb), 1024) == -1) {
        perror("pread");
        close(fd);
        return 1;
    }

    // 读取ext4组描述符
    struct ext4_group_desc gd;
    if (pread(fd, &gd, sizeof(gd), 4096) == -1) {
        perror("pread");
        close(fd);
        return 1;
    }

    // 读取Inode并打印文件权限信息
    struct ext4_inode inode;
    if (pread(fd, &inode, sizeof(inode), gd.bg_inode_table * 4096) == -1) {
        perror("pread");
        close(fd);
        return 1;
    }

    // 打印超级块和组描述符信息
    print_superblock(&sb);

    // 打印组描述符信息
    print_group_descriptor(&gd);

    // 打印文件的权限
    print_file_permissions(&inode);

    // 打印数据块号码
    print_inode_data_blocks(fd, &inode);

    // 读取和打印块位图
    print_block_bitmap(fd, &gd);

    // 读取和打印inode位图
    print_inode_bitmap(fd, &gd);

    // 读取和打印其他信息，如位图和inode表项

    // 关闭设备文件
    close(fd);

    return 0;
}
